package cn.wolfcode.luowowo.search.service.impl;

import cn.wolfcode.luowowo.search.query.SearchQueryObject;
import cn.wolfcode.luowowo.search.repository.StrategyTemplateRepository;
import cn.wolfcode.luowowo.search.service.IStrategyTemplateSearchService;
import cn.wolfcode.luowowo.search.template.StrategyTemplate;
import cn.wolfcode.luowowo.search.vo.StatisVO;
import com.alibaba.dubbo.config.annotation.Service;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.bucket.composite.CompositeAggregation;
import org.elasticsearch.search.aggregations.bucket.composite.CompositeAggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.composite.CompositeValuesSourceBuilder;
import org.elasticsearch.search.aggregations.bucket.composite.TermsValuesSourceBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;

import java.util.*;

@Service
public class StrategyTemplateSearchServiceImpl implements IStrategyTemplateSearchService {

    //es 依然使用spring-data-jpa

    //repository 封装了template
    //template 封装了 client

    @Autowired
    private StrategyTemplateRepository repository;
    @Autowired
    private ElasticsearchTemplate template;
    @Autowired
    private TransportClient client;  //java操作es的第三方客户端


    @Override
    public void saveOrUpdate(StrategyTemplate template) {
        repository.save(template);
    }

    //{
    //    "size":0,
    //        "aggs": {
    //    "themeGroup": {
    //        "composite": {
    //            "sources": [
    //            {
    //                "id": {
    //                "terms": {
    //                    "field": "themeId"
    //                }
    //            }
    //            },{
    //                "name": {
    //                    "terms": {
    //                        "field": "themeName"
    //                    }
    //                }
    //            }
    //      ]
    //        }
    //    }
    //}
    //}
    public List<Map<String, Object>> queryThemeCommend() {
        List<Map<String, Object>> data = new ArrayList<>();
        //需求 : 查看主题的排行 , 主题下关联的攻略篇数
        //执行elasticSearch 语句  , 获取要的数据  list<StatisVO>   id name count
        //拼接分组语句        themeGroup 的拼接
        List<StatisVO> themes = this.statisGroup("themeId", "themeName", "themeGroup");
        //获取10个
        if (themes.size() > 10) {
            themes = themes.subList(0, 10);
        }
        //遍历themes  得到每个主题关联目的地的集合
        Map<String, Object> map = null;
        for (StatisVO theme : themes) {
            map = new HashMap<>();
            //map 存放两个对象 , theme 的对象  以及它所拥有的目的地集合对象
            map.put("theme", theme);
            //通过主题id  获取目的地的集合
            List<StatisVO> dests = this.getDestByThemeId(theme.getId());
            map.put("dests", dests);
            data.add(map);
        }
        return data;
    }

    private List<StatisVO> statisGroup(String idField, String nameField, String groupName) {
        List<CompositeValuesSourceBuilder<?>> sources = new ArrayList<>();
        TermsValuesSourceBuilder idSource = new TermsValuesSourceBuilder("id");
        idSource.field(idField);
        TermsValuesSourceBuilder nameSource = new TermsValuesSourceBuilder("name");
        nameSource.field(nameField);
        sources.add(idSource);
        sources.add(nameSource);
        CompositeAggregationBuilder aggBuilder = new CompositeAggregationBuilder(groupName, sources);
        //{}
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
        //组合的方式 , 将分组语句进行拼接
        builder.addAggregation(aggBuilder);
        //对应size  设置为首页一条数据
        builder.withPageable(PageRequest.of(0, 1));

        //开始查询      获取到了数据      解析结果
        AggregatedPage<StrategyTemplate> page = (AggregatedPage<StrategyTemplate>) repository.search(builder.build());
        CompositeAggregation themeGroup = page.getAggregations().get(groupName);

        List<StatisVO> themes = new ArrayList<>();
        //获取buckets进行编咯
        for (CompositeAggregation.Bucket bucket : themeGroup.getBuckets()) {
            Long id = Long.valueOf(bucket.getKey().get("id").toString());
            String name = bucket.getKey().get("name").toString();
            long count = bucket.getDocCount();
            StatisVO statisVO = new StatisVO(id, name, count);
            themes.add(statisVO);
        }

        //需求 : 查看主题的排行 , 主题下关联的攻略篇数 count
        Collections.sort(themes, new Comparator<StatisVO>() {
            //比较器  ,  作用是 返回的数值
            //根据返回的数值 , 进行排序  逆序
            public int compare(StatisVO o1, StatisVO o2) {
                Long ret = o2.getCount() - o1.getCount();  //大的在前面
                return ret.intValue();
            }
        });
        return themes;
    }

    public List<StatisVO> queryConditionThemes() {
        return this.statisGroup("themeId", "themeName", "themeGroup");
    }

    public List<StatisVO> queryConditionCountries() {
        List<StatisVO> voList = this.statisGroup("countryId", "countryName", "countryGroup");
        List<StatisVO> list = new ArrayList<>();
        for (StatisVO vo : voList) {
            if (!"中国".equals(vo.getName())) {
                list.add(vo);
            }
        }
        return list;
    }

    public List<StatisVO> queryConditionProvinces() {
        return this.statisGroup("provinceId", "provinceName", "provinceGroup");

    }

    public Page query2(SearchQueryObject qo) {
        BoolQueryBuilder builder = QueryBuilders.boolQuery();
        //判断是哪个
        if (qo.getType() == SearchQueryObject.CONDITION_TYPE_THEME) {
            //主题
            builder.must(QueryBuilders.termQuery("themeId", qo.getTypeValue()));
        } else if (qo.getType() == SearchQueryObject.CONDITION_TYPE_CHINA) {
            //国内
            builder.must(QueryBuilders.termQuery("provinceId", qo.getTypeValue()));
        } else if (qo.getType() == SearchQueryObject.CONDITION_TYPE_ABROAD) {
            //国外
            builder.must(QueryBuilders.termQuery("countryId", qo.getTypeValue()));
        }
        //默认情况
        return repository.search(builder, qo.getPageable());
    }

    public Page query(SearchQueryObject qo) {
        if (qo.getType() != null && qo.getTypeValue() != null) {
            //判断是哪个
            if (qo.getType() == SearchQueryObject.CONDITION_TYPE_THEME) {
                //主题
                return repository.search(QueryBuilders.termQuery("themeId", qo.getTypeValue()), qo.getPageable());

            } else if (qo.getType() == SearchQueryObject.CONDITION_TYPE_CHINA) {
                //国内
                return repository.search(QueryBuilders.termQuery("provinceId", qo.getTypeValue()), qo.getPageable());
            } else if (qo.getType() == SearchQueryObject.CONDITION_TYPE_ABROAD) {
                //国外
                return repository.search(QueryBuilders.termQuery("countryId", qo.getTypeValue()), qo.getPageable());
            }
        }
        //默认情况
        return repository.findAll(qo.getPageable());
    }

    public List<StrategyTemplate> findByDestName(String name) {
        return repository.findByDestName(name);
    }

    private List<StatisVO> getDestByThemeId(Long themeId) {
        //通过主题id  获取目的地的集合  id  name
        //jpa 语法规范  , findBy属性名
        //去除重复  目的地
        List<String> destName = new ArrayList<>();
        List<StrategyTemplate> list = repository.findByThemeId(themeId);
        List<StatisVO> dests = new ArrayList<>();
        for (StrategyTemplate strategyTemplate : list) {
            if (!destName.contains(strategyTemplate.getDestName())) {
                StatisVO vo = new StatisVO();
                //存放的是目的地id 以及名字
                vo.setId(strategyTemplate.getDestId());
                vo.setName(strategyTemplate.getDestName());

                dests.add(vo);
                destName.add(strategyTemplate.getDestName());
            }
        }
        return dests;
    }

}
